package com.rq.app_base.android;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.base.rq.LOG;
import com.base.rq.R;
import com.rq.app_base.BASE;
import com.rq.app_base.CtrUI;
import com.rq.app_base.SystemAdapter;
import com.rq.app_base.android.event.ClassGetter;
import com.rq.app_base.android.event.OnClick;
import com.rq.app_base.android.event.OnRefuseAndLoad;
import com.rq.app_base.android.event.OnRefuseAndLoadListener;
import com.rq.app_base.use.BaseController;
import com.rq.app_base.use.BaseFragment;
import com.rq.app_base.use.CommonFragment;
import com.rq.rvlibrary.BaseAdapter;
import com.rq.rvlibrary.RecyclerUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;

/**
 * @author RQ
 * date    2021-07-09 14:03
 */
public class AndroidSystemAdapter implements SystemAdapter<View, Context> {

  public synchronized void send2Target(Object obj, Object... data) {
    int index = 1;
    StackTraceElement[] stacks = new Exception().getStackTrace();
    String methodName = stacks[index].getMethodName(); //获取调用者的方法名
    LOG.d("AndroidSystemAdapter", "send2Target.50:" + obj.getClass().getSimpleName());
    LOG.d("AndroidSystemAdapter", "send2Target.51:" + methodName);
    Method method = null;
    for (Method m : obj.getClass().getMethods()) {
      if (methodName.equals(m.getName())) {
        method = m;
      } else {
        LOG.d("AndroidSystemAdapter", "send2Target.56:" + m.getName());
      }
    }
    if (method == null) {
      LOG.d("AndroidSystemAdapter", "send2Target.58:");
      return;
    }
    Annotation[] annotations = method.getAnnotations();
    if (annotations.length > 0) {
      for (Annotation annotation : annotations) {
        if (annotation instanceof ClassGetter) {
          ClassGetter inject = (ClassGetter) annotation;
          Class c = inject.clazz();
          String name = inject.name();
          Class[] param = inject.param();
          toInvoke(c, name, param, mCtrUI, data);
        }
      }
    }
  }

  private void toInvoke(Class c, String name, Class[] param, Object obj, Object[] data) {
    if (uiIsFrom(c)) {
      try {
        LOG.e("AndroidSystemAdapter", "toInvoke.76:" + c.getSimpleName());
        LOG.e("AndroidSystemAdapter", "toInvoke.77:" + obj.getClass().getSimpleName());
        LOG.e("AndroidSystemAdapter", "toInvoke.78:" + param.length);
        Method sender = c.getDeclaredMethod(name, param);
        if (data.length > 0) {
          sender.invoke(obj, data);
        } else {
          sender.invoke(obj);
        }
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    } else {
      LOG.printWhere(mCtrUI, c, name);
    }
  }

  protected final boolean uiIsFrom(Class<?> clazz) {
    boolean res = clazz.isAssignableFrom(mCtrUI.getClass());
    return res;
  }

  enum ViewParam {
    //View.setEnable(true)
    ENABLE,
    //View.setEnable(false)
    UNABLE,
    //View.setCheckable(true)
    CHECKABLE,
    //View.setCheckable(false)
    UNCHECKABLE
  }

  CtrUI<View> mCtrUI;

  public AndroidSystemAdapter(CtrUI ui) {
    this.mCtrUI = ui;
  }

  public void checkUiEvent(Object ui) {
    LOG.e("AndroidSystemAdapter", "checkUiEvent.61:");
    if (is(View.OnClickListener.class, ui)) {
      LOG.e("AndroidSystemAdapter", "checkUiEvent.63:");
      Method method = null;
      try {
        method = get(View.OnClickListener.class, ui).getClass()
                                                    .getDeclaredMethod("onClick", View.class);
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      }
      if (method == null) {
        return;
      }
      LOG.e("AndroidSystemAdapter", "checkUiEvent.116:" + method.getName());
      Annotation[] annotations = method.getAnnotations();
      if (annotations.length > 0) {
        for (Annotation annotation : annotations) {
          if (annotation instanceof OnClick) {
            OnClick inject = (OnClick) annotation;
            int[] value = inject.value();
            if (value.length > 0) {
              for (int id : value) {
                setData2View(id, get(View.OnClickListener.class, ui));
              }
            }
          }
        }
      }
    }
    if (is(OnRefuseAndLoadListener.class, ui)) {
      LOG.e("AndroidSystemAdapter", "checkUiEvent.90:");
      Method method = null;
      try {
        method = get(OnRefuseAndLoadListener.class, ui).getClass()
                                                       .getDeclaredMethod("refuse", int.class);
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      }
      if (method == null) {
        return;
      }
      Annotation[] annotations = method.getAnnotations();
      if (annotations.length > 0) {
        for (Annotation annotation : annotations) {
          if (annotation instanceof OnRefuseAndLoad) {
            OnRefuseAndLoad inject = (OnRefuseAndLoad) annotation;
            int id = inject.viewId();
            if (id > 0) {
              setOnRefuseAndLoadListener(id, get(OnRefuseAndLoadListener.class, ui), inject
                  .loadAble(), inject.refuseAble());
            }
          }
        }
        get(OnRefuseAndLoadListener.class, ui).refuse(BASE.PAGE_SIZE_START);
      }
    }
  }

  protected final boolean is(Class<?> clazz, Object obj) {
    //    boolean res = clazz.isAssignableFrom(obj.getClass());
    return clazz.isAssignableFrom(obj.getClass());
  }

  public <T> T get(Class<T> type, Object obk) {
    return type.cast(obk);
  }

  /**
   * 为了简化逻辑 ，会在设置View的时候加载一次 refuse(1)
   * RefreshAble 默认 true
   *
   * @param refuseAndLoad boolean + boolean >>LoadAble + RefreshAble
   *                      null 根据 SmartRefreshLayout父布局 外层高度 与 SmartRefreshLayout 高度自行设置 LoadAble
   */
  public void setOnRefuseAndLoadListener(int viewId, final OnRefuseAndLoadListener listener,
                                         Object... refuseAndLoad) {

  }

  public synchronized int setData2View(int id, Object data) {
    return setData2View(mCtrUI.getView(id), data);
  }

  @Override
  public synchronized int setData2View(View view, Object obj) {
    if (view == null) {
      Log.e("AndroidSystemAdapter", "视图为空");
      return 2;
    }
    if (obj == null) {
      Log.e("AndroidSystemAdapter", "数据为空");
      return 3;
    }
    if ((obj instanceof Integer)) {
      if ((int) obj == View.VISIBLE || (int) obj == View.GONE || (int) obj == View.INVISIBLE) {
        view.setVisibility((int) obj);
        return 1;
      }
    }
    if (obj instanceof ViewParam) {
      if (obj == ViewParam.ENABLE) {
        view.setEnabled(true);
      } else if (obj == ViewParam.UNABLE) {
        view.setEnabled(false);
      } else if (obj == ViewParam.CHECKABLE) {
        view.setClickable(true);
      } else if (obj == ViewParam.UNCHECKABLE) {
        view.setClickable(false);
      }
      return 1;
    }
    if (obj instanceof View.OnClickListener) {
      view.setOnClickListener((View.OnClickListener) obj);
      return 1;
    }
    if (view instanceof ImageView) {
      fillImageView((ImageView) view, obj);
    } else if (view instanceof TextView) {
      fillTextView((TextView) view, obj);
    } else if (view instanceof RecyclerView) {
      LOG.e("BaseController", "setDataToView.833:");
      if (obj instanceof RecyclerUtil) {
        fillRecyclerViewData((RecyclerView) view, (RecyclerUtil) obj);
      } else {
        fillRecyclerViewData((RecyclerView) view, obj);
      }
    } else if (view instanceof FrameLayout) {
      try {
        fillFrameLayout((FrameLayout) view, obj);
      } catch (Exception e) {
        LOG.e("AndroidSystemAdapter", "请使用 FragmentActivity 或者重写 super.setData2View() 前");
      }
    }
    return 0;
  }

  private void fillRecyclerViewData(RecyclerView view, Object obj) {
    if (obj instanceof BaseAdapter) {
      new RecyclerUtil((BaseAdapter) obj).set2View(view);
    } else if (obj instanceof RecyclerView.Adapter) {
      new RecyclerUtil((RecyclerView.Adapter) obj).set2View(view);
    } else if (obj instanceof RecyclerView.LayoutManager) {
      view.setLayoutManager((RecyclerView.LayoutManager) obj);
    } else if (obj instanceof RecyclerView.ItemDecoration) {
      view.addItemDecoration((RecyclerView.ItemDecoration) obj);
    }
  }

  FragmentManager mFragmentManager;

  private void fillFrameLayout(FrameLayout view, Object obj) throws Exception {
    if (mFragmentManager == null) {
      mFragmentManager = getActivity().getSupportFragmentManager();
    }
    FragmentTransaction mFragmentTransaction = mFragmentManager.beginTransaction();
    BaseFragment fragment = null;
    if (obj instanceof Class) {
      fragment = CommonFragment.instance((Class<BaseController>) obj);
    } else if (obj instanceof BaseFragment) {
      fragment = (BaseFragment) obj;
    }
    if (fragment == null) {
      LOG.e("BaseController", "fillFrameLayout.fragment == null");
      return;
    }
    FragmentTransaction ft = mFragmentTransaction;
    LOG.e("BaseController", "fillFrameLayout.fragment.getStrTag():" + fragment.getStrTag());
    Fragment showFg = null;
    String tagPage = null;
    Fragment show = null;
    for (Fragment item : mFragmentManager.getFragments()) {
      if (!item.isHidden()) {
        show = item;
      }
    }
    try {
      tagPage = (String) view.getTag(R.id.tag_key);
      showFg = mFragmentManager.findFragmentByTag(tagPage);
    } catch (Exception e) {
    }
    if (!fragment.isAdded() && null == mFragmentManager.findFragmentByTag(tagPage)) {
      if (showFg != null) {
        ft.hide(showFg).add(view.getId(), fragment, tagPage);
      } else {
        view.setTag(R.id.tag_key, tagPage);
        ft.add(view.getId(), fragment, tagPage);
      }
    } else { //已经加载进容器里去了....
      if (show != null) {
        ft.hide(show).show(fragment);
      } else {
        ft.show(fragment);
      }
    }
    if (!getActivity().isFinishing()) {
      ft.commitAllowingStateLoss();
      getActivity().getSupportFragmentManager().executePendingTransactions();
    }
  }

  private FragmentActivity getActivity() throws Exception {
    if (mCtrUI instanceof FragmentActivity) {
      return (FragmentActivity) mCtrUI;
    } else if (mCtrUI instanceof Fragment) {
      return ((Fragment) mCtrUI).getActivity();
    }
    throw new Exception("");
  }

  private int fillTextView(TextView view, Object obj) {
    if (obj instanceof CharSequence) {
      view.setText((CharSequence) obj);
      return 1;
    } else if (obj instanceof Integer) {
      view.setText((int) obj);
      return 1;
    }
    return 0;
  }

  private int fillImageView(ImageView view, Object obj) {
    LOG.e("BaseController", (obj instanceof Drawable) + ".1126:" + obj.getClass());
    if (obj instanceof Bitmap) {
      view.setImageBitmap((Bitmap) obj);
      return 1;
    } else if (obj instanceof Integer) {
      view.setImageResource((int) obj);
      return 1;

    } else if (obj instanceof Drawable) {
      view.setImageDrawable((Drawable) obj);
      return 1;

    } else if (obj instanceof String) {
      String con = (String) obj;
      if (con.startsWith("#")) {
        view.setBackgroundColor(Color.parseColor(con));
        return 1;
      } else if (con.startsWith("http")) {
        // TODO: 2021-07-13  
        //        ImageLoadUtil.display(getContext(), (String) obj, view);
      } else {
        LOG.e("BaseController", "fillImageView.未知图片:" + con);
      }
    }
    return 0;
  }

  @Override
  public View getView(int id) {
    return mCtrUI.getView(id);
  }

  @Override
  public Context getContext() {
    return mCtrUI.getContext();
  }
}
